package com.zmn.plat.dubbo.impl.orderconfig.distribute;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

import com.alibaba.fastjson.JSONObject;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.manager.common.database.annotation.ReadOnlyConnection;
import com.zmn.manager.common.utils.CacheConsts;
import com.zmn.manager.redis.RedisManager;
import com.zmn.plat.business.interfaces.orderconfig.distribute.DistributeWeightPlatBService;
import com.zmn.plat.business.interfaces.orderconfig.distribute.RobOrderConfigBService;
import com.zmn.plat.common.constant.DistributeWeightRelationConstant;
import com.zmn.plat.common.dictionary.DistributeWayEnum;
import com.zmn.plat.common.dto.orderconfig.distribute.RobOrderDIO;
import com.zmn.plat.common.dto.product.item.ItemDRO;
import com.zmn.plat.dubbo.constant.DistributeConsts;
import com.zmn.plat.dubbo.dto.orderconfig.distribute.*;
import com.zmn.plat.model.entity.orderconfig.distribute.*;
import com.zmn.plat.services.interfaces.orderconfig.distribute.DistributeWeightRelationService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.plat.business.interfaces.mast.DistributeWeightBService;
import com.zmn.plat.dubbo.interfaces.orderconfig.distribute.DistributeWeightListRemoteService;
import com.zmn.plat.model.vo.mast.DistributeWeightVO;
import com.zmn.plat.dubbo.utils.DubboConsts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * 类描述：派单参数查询远程查询接口实现
 *
 * @author mujunlin
 * @since 2020/03/03 22:16
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 5000, retries = -1, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class DistributeWeightListRemoteServiceImpl implements DistributeWeightListRemoteService {

    @Resource
    private DistributeWeightBService distributeWeightBusinessService;

    @Resource
    private DistributeWeightPlatBService distributeWeightPlatBusinessService;

    @Resource
    private DistributeWeightRelationService distributeWeightRelationService;

    @Resource
    private RobOrderConfigBService robOrderConfigBService;

    @Resource
    private RedisManager redisManager;

    private final int SECOND_OF_HOURS = 60 * 60 * 24;

    @Override
    @ReadOnlyConnection
    public ResponseDTO<DistributeArgsDRO> findDistributeArgsById(@NotNull(message = "平台ID不能为空") Integer plat, @NotNull(message = "公司ID不能为空") Integer companyId,
                                                                 @NotNull(message = "城市ID不能为空") Integer cityId, @NotNull(message = "业务类型不能为空") Integer bizType) {

        DistributeWeightVO vo = distributeWeightBusinessService.findDistributeWeightById(plat, companyId, cityId, bizType);
        if (Objects.isNull(vo)) {
            log.debug("#DistributeWeightListRemoteServiceImpl#findDistributeArgsById#未查询到派单参数信息。plat:{}, companyId:{}, cityId:{}", plat, companyId, cityId);
            return ResponseDTO.success(null, "暂无配置信息");
        }
        DistributeArgsDRO dro = BeanMapper.map(vo, DistributeArgsDRO.class);
        distributeArgsParameterAssembly(dro, vo.getDistributeApplication(), vo.getDistributeConfigId());
        return ResponseDTO.success(dro, GlobalConsts.SUCCESS_MSG);
    }

    @Override
    @ReadOnlyConnection
    public ResponseDTO<DistributeConfigDRO> findDistributeConfig(@NotNull(message = "平台ID不能为空") Integer plat,
                                                                 @NotNull(message = "公司ID不能为空") Integer companyId,
                                                                 @NotNull(message = "城市ID不能为空") Integer cityId,
                                                                 @NotNull(message = "业务类型不能为空") Integer bizType) {

        // 获取平台直派配置
        DistributeWeightPlat distributeWeightPlat = distributeWeightPlatBusinessService.findPlatDirectlyConfigByPlatAndBizTypeAndCityId(plat, bizType, cityId);
        // 计算是否应该平台直派
        boolean isPlatDirectly = Objects.nonNull(distributeWeightPlat);
        DistributeWayEnum distributeWay;
        PlatDirectlyDistributeArgsDRO platDirectlyDistributeArgs;
        if (isPlatDirectly) {
            platDirectlyDistributeArgs = new PlatDirectlyDistributeArgsDRO();
            BeanUtils.copyProperties(distributeWeightPlat, platDirectlyDistributeArgs);
            distributeWay = DistributeWayEnum.DISTRIBUTE_WAY_PLAT;
            distributeArgsParameterAssembly(platDirectlyDistributeArgs, DistributeWeightRelationConstant.DISTRIBUTE_APPLICATION_PLAT, distributeWeightPlat.getDistributePlatId());
        } else {
            platDirectlyDistributeArgs = null;
            distributeWay = DistributeWayEnum.DISTRIBUTE_WAY_SP;
        }
        // 获取服务商派单配置
        log.debug("#distributeWeightBusinessService#findDistributeWeightById#获取服务商派单配置reqParam,plat:{}, companyId:{}, cityId:{},bizType:{}",plat, companyId, cityId, bizType );
        DistributeWeightVO distributeWeightVO = distributeWeightBusinessService.findDistributeWeightById(plat, companyId, cityId, bizType);
        log.debug("#distributeWeightBusinessService#findDistributeWeightById#获取服务商派单配置respParam:{}", JSONObject.toJSON(distributeWeightVO));
        DistributeArgsDRO distributeArgs = BeanMapper.map(distributeWeightVO, DistributeArgsDRO.class);
        Integer distributeApplication =Objects.nonNull(distributeWeightVO)?distributeWeightVO.getDistributeApplication():null;
        Integer distributeConfigId = Objects.nonNull(distributeWeightVO)?distributeWeightVO.getDistributeConfigId():null;
        distributeArgsParameterAssembly(distributeArgs,distributeApplication ,distributeConfigId );
        return ResponseDTO.success(new DistributeConfigDRO(platDirectlyDistributeArgs, distributeArgs, distributeWay.getCode()), "获取成功");

    }

    @Override
    public ResponseDTO<RobOrderDRO> findRobOrderConfig(RobOrderDIO query) {

        RobOrderDRO robOrderDRO =new RobOrderDRO();
        String redisKey = query.getCityId()+":"+query.getCompanyId();
        //先去缓存查，有则返回，无则查询
        String redisData = redisManager.get("plat:orderConfig:robOrderConfig"+":"+redisKey);
        if(StringUtils.isNotBlank(redisData)){
            robOrderDRO = JSONObject.parseObject(redisData, RobOrderDRO.class);
            return ResponseDTO.success(robOrderDRO, GlobalConsts.SUCCESS_MSG);
        }
       // query.setDistributeWay(DistributeConsts.DISTRIBUTE_PLAT_DIRECTLY);
        //RobOrderConfigInfo robOrderConfigInfo =  robOrderConfigBService.findRobOrderConfigByQuery(query);
        // 计算是否应该平台直派
        //boolean isPlatDirectly = Objects.nonNull(robOrderConfigInfo);

        DistributeWayEnum distributeWay;
        PlatDirectlyConfigDRO platDirectlyConfigDRO = new PlatDirectlyConfigDRO() ;
        CompanyConfigDRO companyConfigDRO = new CompanyConfigDRO();
        //平台直派
        if(DistributeConsts.DISTRIBUTE_PLAT_DIRECTLY.equals(query.getDistributeWay())){
            distributeWay = DistributeWayEnum.DISTRIBUTE_WAY_PLAT;
            RobOrderConfigInfo robOrderConfigInfo =  robOrderConfigBService.findRobOrderConfigByQuery(query);
            if(Objects.nonNull(robOrderConfigInfo)){
                List<RobOrderRelationDRO> resultList = getRelationData(robOrderConfigInfo);
                BeanUtils.copyProperties(robOrderConfigInfo,platDirectlyConfigDRO);
                platDirectlyConfigDRO.setRobOrderRelationList(resultList);
                robOrderDRO.setDistributeWay(distributeWay.getCode());
                robOrderDRO.setPlatDirectlyConfigDRO(platDirectlyConfigDRO);
            }
        }
        if(DistributeConsts.DISTRIBUTE_SERVICE_PROVIDER.equals(query.getDistributeWay())){
            query.setDistributeWay(null);
            RobOrderConfigInfo robOrderCompanyConfig =  robOrderConfigBService.findCompanyRobOrderConfigByQuery(query);
            //取公司配置，没有取平台配置
            if(Objects.nonNull(robOrderCompanyConfig)){
                List<RobOrderRelationDRO> resultList = getRelationData(robOrderCompanyConfig);
                BeanUtils.copyProperties(robOrderCompanyConfig,companyConfigDRO);
                companyConfigDRO.setRobOrderRelationList(resultList);

                robOrderDRO.setDistributeWay(DistributeConsts.DISTRIBUTE_SERVICE_PROVIDER);
                robOrderDRO.setCompanyConfigDRO(companyConfigDRO);
            }else{
                //查服务商平台的数据，cityId改为null
                query.setCityId(null);
                query.setCompanyId(null);
                redisKey = query.getCityId()+":"+query.getCompanyId();
                query.setDistributeWay(DistributeConsts.DISTRIBUTE_SERVICE_PROVIDER);
                String redisData1 = redisManager.get("plat:orderConfig:robOrderConfig"+":"+redisKey);
                if(StringUtils.isNotBlank(redisData1)){
                    robOrderDRO = JSONObject.parseObject(redisData1, RobOrderDRO.class);
                    return ResponseDTO.success(robOrderDRO, GlobalConsts.SUCCESS_MSG);
                }
                RobOrderConfigInfo robOrderPlatConfig =  robOrderConfigBService.findRobOrderConfigByQuery(query);
                if(Objects.nonNull(robOrderPlatConfig)){
                    List<RobOrderRelationDRO> resultList = getRelationData(robOrderPlatConfig);
                    BeanUtils.copyProperties(robOrderPlatConfig,companyConfigDRO);
                    companyConfigDRO.setRobOrderRelationList(resultList);
                    robOrderDRO.setDistributeWay(DistributeConsts.DISTRIBUTE_SERVICE_PROVIDER);
                }
                robOrderDRO.setCompanyConfigDRO(companyConfigDRO);
            }
        }
        //查询成功把配置数据写入缓存
        redisManager.setex("plat:orderConfig:robOrderConfig"+":"+redisKey, JSONObject.toJSONString(robOrderDRO), SECOND_OF_HOURS);
        return ResponseDTO.success(robOrderDRO, GlobalConsts.SUCCESS_MSG);
    }

    private List<RobOrderRelationDRO> getRelationData(RobOrderConfigInfo robOrderConfigInfo){
        RobOrderRelationQuery robOrderRelationQuery =RobOrderRelationQuery.builder()
                .configId(robOrderConfigInfo.getConfigId())
                .build();
        List<RobOrderRelation> robOrderRelationList = robOrderConfigBService.listByQuery(robOrderRelationQuery);
        List<RobOrderRelationDRO> resultList = new ArrayList<>();
        if(CollectionUtil.isNotNullOrEmpty(robOrderRelationList)){
            resultList = robOrderRelationList.stream().map(rs -> {
                RobOrderRelationDRO dro = new RobOrderRelationDRO();
                BeanUtils.copyProperties(rs, dro);
                return dro;
            }).collect(Collectors.toList());
            resultList.forEach(item ->{
                RobOrderRelationProductQuery robOrderRelationProductQuery = RobOrderRelationProductQuery.builder()
                        .relationId(item.getRelationId())
                        .build();
                List<RobOrderRelationProduct> robOrderRelationProductList = robOrderConfigBService.listProductByQuery(robOrderRelationProductQuery);
                List<RobOrderRelationProductDRO> itemDROS = robOrderRelationProductList.stream().map(i -> {
                    RobOrderRelationProductDRO dro = new RobOrderRelationProductDRO();
                    BeanUtils.copyProperties(i, dro);
                    return dro;
                }).collect(Collectors.toList());
                item.setRobOrderRelationProductList(itemDROS);

            });
        }
        return resultList;
    }

    /**
     * 工程师派单权重关联配置数据
     * @param distributeApplication 派单应用：1.平台， 2.公司
     * @param distributeConfigId 派单配置id(派单应用为平台时取平台派单权重配置id，为公司时取公司派单权重配置id)
     * @return List<DistributeWeightRelation>
     * @author xujie
     * @since  2021-06-08
     */
    private List<DistributeWeightRelation> distributeWeightRelationData(Integer distributeApplication,
                                                                        Integer distributeConfigId) {

        DistributeWeightRelationQuery query = DistributeWeightRelationQuery.builder()
                .distributeConfigId(distributeConfigId)
                .distributeApplication(distributeApplication)
                .build();
        List<DistributeWeightRelation> distributeWeightRelationList = NumberUtil.isNullOrZero(distributeConfigId) ?
                new ArrayList<>() :
                distributeWeightRelationService.listByQuery(query);
        // 直营工程师权重默认数据
        DistributeWeightRelation distributeWeightRelation = DistributeWeightRelation
                .builder()
                .distanceWeight(40)
                .handlerWeight(30)
                .daySuccessWeight(30)
                .successRateWeight(0)
                .visitRateWeight(0)
                .atvAmountWeight(0)
                .starLevelScoreWeight(0)
                .weightType(DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY)
                .distributeApplication(distributeApplication)
                .distributeConfigId(distributeConfigId)
                .build();
        // 非直营工程师权重默认数据
        DistributeWeightRelation distributeWeightRelationNon = DistributeWeightRelation
                .builder()
                .distanceWeight(40)
                .handlerWeight(30)
                .daySuccessWeight(30)
                .successRateWeight(0)
                .visitRateWeight(0)
                .atvAmountWeight(0)
                .starLevelScoreWeight(0)
                .weightType(DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY_NON)
                .distributeApplication(distributeApplication)
                .distributeConfigId(distributeConfigId)
                .build();
        if (distributeWeightRelationList.size() == 0) {
            distributeWeightRelationList.add(distributeWeightRelation);
            distributeWeightRelationList.add(distributeWeightRelationNon);
        } else if (distributeWeightRelationList.size() == 1) {
            DistributeWeightRelation d = distributeWeightRelationList.get(0);
            if (DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY.equals(d.getWeightType())) {
                distributeWeightRelationList.add(distributeWeightRelationNon);
            } else if (DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY_NON.equals(d.getWeightType())) {
                distributeWeightRelationList.add(distributeWeightRelation);
            } else {
                distributeWeightRelationList.add(distributeWeightRelation);
                distributeWeightRelationList.add(distributeWeightRelationNon);
            }
        }
        return distributeWeightRelationList;
    }

    /**
     * 派单参数配置配置数据组装
     * @param distributeArgs 派单参数配置配置
     * @param distributeApplication 派单应用：1.平台， 2.公司
     * @param distributeConfigId 派单配置id(派单应用为平台时取平台派单权重配置id，为公司时取公司派单权重配置id)
     * @author xujie
     * @since  2021-06-08
     */
    private void distributeArgsParameterAssembly(DistributeArgsDRO distributeArgs, Integer distributeApplication, Integer distributeConfigId) {

        if (distributeArgs == null) {
            return;
        }
        List<DistributeWeightRelation> weightRelationList = distributeWeightRelationData(distributeApplication, distributeConfigId);
        // 直营
        Optional<DistributeWeightRelation> optional = weightRelationList.stream().filter(w -> DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY.equals(w.getWeightType())).findFirst();
        // 非直营
        Optional<DistributeWeightRelation> optionalNon = weightRelationList.stream().filter(w -> DistributeWeightRelationConstant.WEIGHT_TYPE_DIRECTLY_NON.equals(w.getWeightType())).findFirst();
        if (optional.isPresent()) {
            DistributeWeightRelation weightRelation = optional.get();
            distributeArgs.setDistanceWeight(weightRelation.getDistanceWeight());
            distributeArgs.setHandlerWeight(weightRelation.getHandlerWeight());
            distributeArgs.setDaySuccessWeight(weightRelation.getDaySuccessWeight());
            distributeArgs.setVisitRateWeight(weightRelation.getVisitRateWeight());
            distributeArgs.setSuccessRateWeight(weightRelation.getSuccessRateWeight());
            distributeArgs.setAvtAmountWeight(weightRelation.getAtvAmountWeight());
            distributeArgs.setStarLevelScoreWeight(weightRelation.getStarLevelScoreWeight());
            distributeArgs.setDistributeNewCount(weightRelation.getDistributeNewCount());
            distributeArgs.setServeScore(weightRelation.getServeScore());
            distributeArgs.setDatumOrderHourRatio(weightRelation.getDatumOrderHourRatio());
        }
        if (optionalNon.isPresent()) {
            DistributeWeightRelation weightRelationNon = optionalNon.get();
            distributeArgs.setDistanceWeightNon(weightRelationNon.getDistanceWeight());
            distributeArgs.setHandlerWeightNon(weightRelationNon.getHandlerWeight());
            distributeArgs.setDaySuccessWeightNon(weightRelationNon.getDaySuccessWeight());
            distributeArgs.setVisitRateWeightNon(weightRelationNon.getVisitRateWeight());
            distributeArgs.setSuccessRateWeightNon(weightRelationNon.getSuccessRateWeight());
            distributeArgs.setAvtAmountWeightNon(weightRelationNon.getAtvAmountWeight());
            distributeArgs.setStarLevelScoreWeightNon(weightRelationNon.getStarLevelScoreWeight());
            distributeArgs.setDistributeNewCountNon(weightRelationNon.getDistributeNewCount());
            distributeArgs.setServeScoreNon(weightRelationNon.getServeScore());
            distributeArgs.setDatumOrderHourRatioNon(weightRelationNon.getDatumOrderHourRatio());
        }
    }



}
